
package soldats;

import java.util.ArrayList;

public class IMeilleurJoueur implements IJoueur
{
    private String coupAlphaBeta = "";
    private int couleurMeilleurJoueur = 0;
    private int couleurPireEnnemi=0;
    private int[][] plateauJeu={{0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0},
                                {1,0,1,1,0,2,2,0,2},
                                {0,1,1,1,0,2,2,2,0},
                                {1,1,1,1,0,2,2,2,2},
                                {0,1,1,1,0,2,2,2,0},
                                {1,0,1,1,0,2,2,0,2},
                                {0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0}};

    /*
    private int[][] plateauJeu={{0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0},
                                {0,0,1,0,1,2,0,0,0},
                                {0,0,1,1,0,2,2,0,0},
                                {0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0}};
    */
    private int[] XInc = {0,-1,0,1,+1,-1,-1,+1};
    private int[] YInc = {-1,0,1,0,-1,-1,+1,+1};

    private int[][] SMoves= {{0,0,83,0,134,0,15,0,0},
            {0,0,0,386,1234,157,0,0,0},
            {84,0,384,134,12345678,143,154,0,54},
            {0,486,243,12345678,1234,12345678,124,754,0},
            {243,1234,12345678,1234,12345678,1234,12345678,1234,241},
            {0,275,243,12345678,1234,12345678,124,268,0},
            {27,0,372,132,12345678,123,162,0,62},
            {0,0,0,375,1234,168,0,0,0},
            {0,0,73,0,132,0,16,0,0}};

    public IMeilleurJoueur()
    {

    }

    public void initJoueur(int mycolour)
    {
        couleurMeilleurJoueur = mycolour;
        couleurPireEnnemi = (mycolour % 2) + 1;
    }

    public int getNumJoueur()
    {
        return couleurMeilleurJoueur;
    }


    //System.out.println("Voici mon mouvement : " + msg);
    public String choixMouvement()
    {
        coupAlphaBeta = "";
        int heuris = 0;

        heuris = alphaBeta(-999999,999999,4,-1,plateauJeu);
        System.out.println("Heuristique = "+heuris+" Coups = "+coupAlphaBeta);

        String coupTab[] = coupAlphaBeta.split(" ");

        plateauJeu = majPlateau(Integer.parseInt(coupTab[0])-1
                , Integer.parseInt(coupTab[1])-1
                , Integer.parseInt(coupTab[2])-1
                , Integer.parseInt(coupTab[3])-1,couleurMeilleurJoueur,plateauJeu);

        return coupAlphaBeta+'\0';
    }

    public void declareLeVainqueur(int colour)
    {
        if(colour == couleurMeilleurJoueur)
            System.out.println("ON TE L'A COLLE §§§§");
        else
            System.out.println("Fuck this shit !");
    }

    public void mouvementEnnemi(int startCol, int startRow, int finishCol, int finishRow)
    {
        plateauJeu = majPlateau(startCol-1,startRow-1,finishCol-1,finishRow-1,couleurPireEnnemi,plateauJeu);
    }

    public String binoName()
    {
        return "Patel-Praud";
    }

    public int[][] majPlateau(int startCol, int startRow, int finishCol, int finishRow, int couleurJoueur, int[][] plateauAModifie)
    {
        int[][] plateauRetour = new int[TAILLE][TAILLE];

        for(int i=0;i<TAILLE;++i)
        {
            for(int j=0;j<TAILLE;++j)
            {
                plateauRetour[i][j]=plateauAModifie[i][j];
            }
        }
        boolean ligne = false;
        boolean colonne = false;

        if(Math.abs(finishCol-startCol)>1)
            colonne = true;
        if (Math.abs(finishRow-startRow)>1)
            ligne = true;
        if(colonne && ligne)
            plateauRetour[finishCol-((finishCol-startCol)/2)][finishRow-((finishRow-startRow)/2)]=0;
        else if(colonne)
            plateauRetour[finishCol-((finishCol-startCol)/2)][finishRow]=0;
        else if(ligne)
            plateauRetour[finishCol][finishRow-((finishRow-startRow)/2)]=0;

        plateauRetour[startCol][startRow]=0;
        plateauRetour[finishCol][finishRow]=couleurJoueur;

        return plateauRetour;
    }

    public int calculHeuristique(int[][] plateauCourant)
    {
        return calculNombrePions(plateauCourant);
    }

    public int calculNombrePions(int[][] plateauCourant)
    {
        int blanc = 0;
        int noir = 0;
        int diff = 0;

        for(int i=0;i<TAILLE;++i)
        {
            for(int j=0;j<TAILLE;++j)
            {
                if(plateauCourant[i][j]==BLANC)
                    blanc++;
                else if(plateauCourant[i][j]==NOIR)
                        noir++;
            }
        }

        if(couleurMeilleurJoueur==BLANC)
            diff = blanc - noir;
        else
            diff = noir - blanc;

        return diff;
    }

    public int coupsEstPossible(int[][] plateauCourant, int posX, int posY, int mouvement, int couleur)
    {
        int couleurCourante = couleur;
        int couleurAdversaire = (couleur % 2) + 1;

        //System.out.println("posX = "+(posX+1)+" posY = "+(posY+1)+" mouvement = "+mouvement+" couleur = "+couleur);

        int mouvX = XInc[mouvement-1];
        int mouvY = YInc[mouvement-1];

        int finalX = posX+mouvX;
        int finalY = posY+mouvY;

        if(plateauCourant[finalX][finalY]==couleurCourante)
            return 0;//Mouvement impossible

        if(plateauCourant[finalX][finalY]==couleurAdversaire && directionValide(finalX, finalY, mouvement))
        {
            finalX+=mouvX;
            finalY+=mouvY;

           if(plateauCourant[finalX][finalY]==0 && SMoves[finalX][finalY]!=0)
               return 2;//Mouvement de prise de pion possible
           else
               return 0;

        }

        if (plateauCourant[finalX][finalY]==0 && SMoves[finalX][finalY]!=0)
            return 1;//Mouvement simple possible
        //else if(plateauCourant[finalX+mouvX][finalY+mouvY]==0 && SMoves[finalX][finalY]!=0)
        //    return 2;

        return 0;
    }

    public ArrayList<Integer> getMouvement(int posX, int posY)
    {
        ArrayList<Integer> listeMouvementPossible = new ArrayList<Integer>();
        int mouvementPossible=SMoves[posX][posY];
        String mouvementString = Integer.toString(mouvementPossible);

        for(int i=0;i<mouvementString.length();++i)
            listeMouvementPossible.add(Integer.parseInt(mouvementString.substring(i,i+1)));

        return listeMouvementPossible;
    }

    public boolean directionValide(int posX, int posY, int mouvement)
    {
        return getMouvement(posX,posY).contains(mouvement);
    }

    private int alphaBeta(int alpha, int beta, int profondeurCible, int profondeur, int[][] plateauCourant)
    {
        int nouvelleProfondeur = profondeur+1;

        //On determine si on est dans un noeud ami ou ennemi
        int couleur;
        if(nouvelleProfondeur%2 == 0)
            couleur = couleurMeilleurJoueur;
        else
            couleur = couleurPireEnnemi;

        //On calcule l'heuristique de la feuille/noeud courant(e)
        int heuristique;
        if(nouvelleProfondeur%2 == 0)
            heuristique = calculHeuristique(plateauCourant);
        else
            heuristique = -calculHeuristique(plateauCourant);

        // Jeu fini, noeud feuille.
        if (heuristique == 888888 || heuristique == -888888)
            return heuristique;

        //On limite la profondeur d'exploration de l'arbre
        //C'est egalement le cas d'arret de notre fonction recursive.
        //On se considere dans un noeud feuille
        if (nouvelleProfondeur==profondeurCible)
            return heuristique;

        // Noeud
        int valAB;
        int meilleur = -999999;

        //Pour tous fils
        //Appel de alphaBeta avec le joueur courant/ tableau de liste des coups possible en fonction de la couleur
        for (String coup : listeCoupsPossibles(couleur,plateauCourant))
        {

            String coupTab[] = coup.split(" ");
            int[][] plateauRetour = majPlateau(Integer.parseInt(coupTab[0])-1
                    , Integer.parseInt(coupTab[1])-1
                    , Integer.parseInt(coupTab[2])-1
                    , Integer.parseInt(coupTab[3])-1, couleur, plateauCourant);

            valAB = -alphaBeta(-beta, -alpha, profondeurCible, nouvelleProfondeur,plateauRetour);

            /*
            plateauCourant = majPlateau(Integer.parseInt(coupTab[2])-1
                    , Integer.parseInt(coupTab[3])-1
                    , Integer.parseInt(coupTab[0])-1
                    , Integer.parseInt(coupTab[1])-1, couleur, plateauCourant);
            */
            if (valAB > meilleur)
            {
                meilleur = valAB;
                if(meilleur > alpha)
                {
                    alpha = meilleur;

                    if (profondeur == -1)
                        coupAlphaBeta = coup;

                    if(alpha>=beta)
                        return meilleur;
                }
            }
            //defaire le coups
        }
        return meilleur;
    }

    public ArrayList<String> listeCoupsPossibles(int couleur, int[][] plateauTmp)
    {
        ArrayList<String> listeRetour = new ArrayList<String>();
        ArrayList<Integer> listeMouvementCourant = new ArrayList<Integer>();
        for(int i=0;i<TAILLE;++i)
        {
            for(int j=0;j<TAILLE;++j)
            {
                if(plateauTmp[i][j]==couleur)
                {
                    listeMouvementCourant = getMouvement(i,j);
                    for (Integer mouvement : listeMouvementCourant)
                    {
                        int mouvementPossible = coupsEstPossible(plateauTmp,i,j,mouvement,couleur);
                        if(mouvementPossible>0)
                        {
                            listeRetour.add((i+1)+" "+(j+1)+" "+((i+1)+(XInc[mouvement-1]*Math.abs(mouvementPossible)))+" "+((j+1)+(YInc[mouvement-1]*Math.abs(mouvementPossible))));
                        }
                    }
                }
            }
        }
        return listeRetour;
    }

}


